package com.hectopascal.interceptor;

import com.hectopascal.BaseResult;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.UUID;

@ControllerAdvice
public class GlobalResponseWrapper implements ResponseBodyAdvice<Object> {
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return BaseResult.class.isAssignableFrom(returnType.getParameterType());
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        UnifiedResponse<Object> wrapped = new UnifiedResponse<>();
        wrapped.setRequestId(UUID.randomUUID().toString().replace("-", ""));
        wrapped.setCode("10000");
        wrapped.setMsg("Success");
        if (body instanceof BaseResult<?> baseResult) {
            wrapped.setResult(baseResult.getResult());
        }
        wrapped.setResult(body);
        // 非 BaseResult 类型直接返回
        return wrapped;
    }

    /**
     * 统一响应结构
     */
    public static class UnifiedResponse<T> {
        private String requestId;
        private String code;
        private String msg;
        private T result;

        public String getRequestId() { return requestId; }
        public void setRequestId(String requestId) { this.requestId = requestId; }

        public String getCode() { return code; }
        public void setCode(String code) { this.code = code; }

        public String getMsg() { return msg; }
        public void setMsg(String msg) { this.msg = msg; }

        public T getResult() { return result; }
        public void setResult(T result) { this.result = result; }
    }
}
